package com.tecklab.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tecklab.demo.common.BizException;
import com.tecklab.demo.dto.DepartmentDTO;
import com.tecklab.demo.dto.EmployeeDTO;
import com.tecklab.demo.dto.HospitalDTO;
import com.tecklab.demo.entity.HospitalEntity;
import com.tecklab.demo.mapper.HospitalMapper;
import com.tecklab.demo.service.DepartmentService;
import com.tecklab.demo.service.EmployeeService;
import com.tecklab.demo.service.HospitalService;
import lombok.SneakyThrows;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * * 用户服务实现类
 */
@Service  // 重要：添加@Service注解 , 标记为Spring服务组件
public class HospitalServiceImpl extends ServiceImpl<HospitalMapper, HospitalEntity> implements HospitalService {

    @Resource
    private HospitalMapper hospitalMapper;

    @Resource
    private DepartmentService departmentService;

    @Resource
    private EmployeeService employeeService;

    //    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @Override
    public int save(HospitalDTO dto) {

        if (StringUtils.isBlank((dto.getName()))) {
            throw new BizException("name不能为空");
        }
        HospitalEntity hospital = this.convertDto2Entity(dto);
        return hospitalMapper.insert(hospital);
    }

    @SneakyThrows
    private HospitalEntity convertDto2Entity(HospitalDTO dto) {
        HospitalEntity entity = new HospitalEntity();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }

    @SneakyThrows
    private HospitalDTO convertEntity2Dto(HospitalEntity entity) {
        HospitalDTO dto = new HospitalDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    @Override
    //根据ID查询医院信息，并展示包含的部门列表
    public HospitalDTO getById(Integer id) {

        if (id == null) {
            throw new BizException("id不能为null");
        }
        LambdaQueryWrapper<HospitalEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(HospitalEntity::getId, id);
        HospitalEntity hospitalEntity = hospitalMapper.selectOne(lambdaQueryWrapper);

        if (hospitalEntity == null) {
            throw new BizException("医院不存在");
        }
        if (StringUtils.isBlank(hospitalEntity.getName())) {
            throw new BizException("医院名字不能是空");
        }
        HospitalDTO hospitalDTO = this.convertEntity2Dto(hospitalEntity);

        List<DepartmentDTO> departmentDTOList = departmentService.getByHospitalId(id);

        for (DepartmentDTO departmentDTO : departmentDTOList) {

            List<EmployeeDTO> employeeDTOList = employeeService.getByDepartmentId(departmentDTO.getId());
            departmentDTO.setEmployeeDTOList(employeeDTOList);
            departmentDTO.setHospitalName(hospitalDTO.getName());

        }
        hospitalDTO.setDepartmentDTOList(departmentDTOList);

        return hospitalDTO;
    }

    @Override
    public HospitalDTO getByName(String name) {
        //name == null  ""  "   "， isBlank() 判断字符串是否为 null、空字符串 "" 或 仅由空白字符组成
        if (StringUtils.isBlank(name)) {
            throw new BizException("医院名字不能为空");
        }
        LambdaQueryWrapper<HospitalEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(HospitalEntity::getName, name);
        //lambdaQueryWrapper.eq(StringUtils.isNoneBlank(name), HospitalEntity::getName, name);
        HospitalEntity hospitalEntity = hospitalMapper.selectOne(lambdaQueryWrapper);
        //HospitalEntity hospitalEntity = super.getOne(lambdaQueryWrapper, false);

        if (hospitalEntity == null) {
            throw new BizException("医院不存在");
        }
        HospitalDTO hospitalDTO = this.convertEntity2Dto(hospitalEntity);

        List<DepartmentDTO> departmentDTOList = departmentService.getByHospitalId(hospitalDTO.getId());

        for (DepartmentDTO departmentDTO : departmentDTOList) {
            List<EmployeeDTO> employeeDTOList = employeeService.getByDepartmentId(departmentDTO.getId());
            departmentDTO.setEmployeeDTOList(employeeDTOList);
            //
            departmentDTO.setHospitalName(hospitalDTO.getName());
        }
        hospitalDTO.setDepartmentDTOList(departmentDTOList);

        return hospitalDTO;
    }

    @Override
    /**
     *@param size:本次最多要创建的记录数量
     */
    public void batchCreateHospital(int size) {
        for (int i = 1; i <= size; i++) {
            HospitalEntity entity = new HospitalEntity();
            entity.setName("诸城市第" + i + "医院");
            hospitalMapper.insert(entity);
        }
    }

    @Override
    public void batchDeleteHospital(int size) {
        // like %XX%
        if (size < 1) {
            throw new RuntimeException("size不能小于1");
        }
        LambdaQueryWrapper<HospitalEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.likeRight(HospitalEntity::getName, "诸城市第")
                .orderByAsc(HospitalEntity::getId)
                .select(HospitalEntity::getId); // 走索引，效率高
        // 查出来
        List<HospitalEntity> entityList = hospitalMapper.selectList(lambdaQueryWrapper);
        // 删除size个
        for (int i = 0; i < size; i++) {
            hospitalMapper.deleteById(entityList.get(i).getId());
        }
    }

    @Override
    /**
     * 批量更新医院实体ID的方法
     * 该方法会将数据库中的医院记录ID按顺序重新编号（从1开始连续递增）
     * @param size 期望更新的记录总数
     * @throws BizException 当没有记录需要更新或更新数量不足时抛出业务异常
     */
    public String batchUpdateId(int size) {
        Object value = redisTemplate.opsForValue().get("zheng");
        log.warn("redis value: " + value);
        String returnMsg;
        // 初始化分页参数：当前页码和每页大小
        int current = 1;
        int pageSize = 2;
        // 初始化计数器：expectedId表示期望的ID值（从1开始递增），updateCount记录已经修改的数量
        int expectedId = 1;
        int updateCount = 0;

        // 循环处理直到更新数量达到预期或没有更多数据
        while (updateCount < size) {
            // 创建分页对象，用于分页查询
            Page<HospitalEntity> page = new Page<>(current, pageSize);
            // 执行分页查询（不带任何查询条件）/第二个参数为查询条件（Wrapper）
            Page<HospitalEntity> pageData = hospitalMapper.selectPage(page, null);

            // 如果当前页没有数据，终止循环
            if (CollectionUtils.isEmpty(pageData.getRecords())) {
                break;
            }

            // 遍历当前页的记录
            for (HospitalEntity hospital : pageData.getRecords()) {

                // 检查是否已达到预期更新数量
                if (updateCount == size) {
                    break;
                }

                // 检查当前记录的ID是否需要更新（与期望ID不匹配的更新）
                if (hospital.getId().intValue() != expectedId) {

                    // 创建Lambda更新条件构造器
                    LambdaUpdateWrapper<HospitalEntity> updateWrapper = new LambdaUpdateWrapper<>();

                    // 设置更新内容和条件：1. 将ID更新为当前期望值(expectedId)，2. 仅更新ID等于当前记录ID的记录
                    updateWrapper.set(HospitalEntity::getId, expectedId)
                            .eq(HospitalEntity::getId, hospital.getId());

                    // 执行更新操作（传入null表示不更新实体，仅按条件更新）
                    hospitalMapper.update(null, updateWrapper);

                    // 更新计数器递增
                    updateCount = updateCount + 1;
                }

                // 无论是否更新，期望ID都递增（保证连续性）
                expectedId = expectedId + 1;
            }

            // 处理下一页
            current = current + 1;
        }
        // 后置检查：
        // 1. 如果没有更新任何记录，抛出业务异常
        // 2. 如果更新数量不足预期，抛出异常并返回实际更新数量
        if (updateCount == 0) {
            returnMsg = "暂时没有要调整的id";
        } else if (updateCount < size) {
            returnMsg = "更新记录数不足，实际更新记录数：" + updateCount;
        } else {
            returnMsg = "所有数据已经更新完毕，更新记录数：" + updateCount;
        }

        return returnMsg;
    }

    @Override
    /**
     * 分页查询
     * new Page(current,size):
     * current:当前页
     * size:   每页记录数
     */
    public Page<HospitalEntity> selectPage(int current, int size) {
        //参数：current当前页、size每页条数
        Page<HospitalEntity> page = new Page<>(current, size);
        //第二个参数为查询条件（Wrapper）
        Page<HospitalEntity> entityPage = hospitalMapper.selectPage(page, null);
//        // 分页的所有数据都在entityPage对象中封装着
//        // 获取总页数
//        long pages = entityPage.getPages();
//        // 获取当前页
//        long currentPage = entityPage.getCurrent();
//        // 获取当前页数据集合
//        List<HospitalEntity> records = entityPage.getRecords();
//        // 获取总记录数
//        long total = entityPage.getTotal();
//        // 当前页是否有下一页
//        boolean hasNext = entityPage.hasNext();
//        // 当前页是否有上一页
//        boolean hasPrevious = entityPage.hasPrevious();

        return entityPage;

        //return hospitalMapper.selectPage(page,null);

    }


}
